package jvs.vfs.opt.media;

import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import java.util.ArrayList;

import jvs.vfs.IFile;
import jvs.vfs.IFileBaseImpl;
import jvs.vfs.opt.ItemInfo;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.provider.MediaStore;
import android.util.Log;

/**
 * @author qiangli
 * 
 */
public class MediaFileImpl extends IFileBaseImpl {

	private static ArrayList<MediaInfo> audiolist = new ArrayList<MediaInfo>();
	private static boolean audioloaded;
	
	private static ArrayList<MediaInfo> recentAudiolist = new ArrayList<MediaInfo>();
	private static boolean recentAudioloaded;
	
	private static ArrayList<MediaInfo> imagelist = new ArrayList<MediaInfo>();
	private static boolean imageloaded;
	
	private static ArrayList<MediaInfo> recentImagelist = new ArrayList<MediaInfo>();
	private static boolean recentImageloaded;
	
//	private static final int INDEX_ = 0;
//	private static final int INDEX_AUDIO = 1;
//	private static final int INDEX_AUDIO_ALBUM = 2;
//	private static final int INDEX_AUDIO_ARTIST = 3;
//	private static final int INDEX_AUDIO_PLAYLIST = 4;
//	private static final int INDEX_AUDIO_SONG = 5;
//	private static final int INDEX_AUDIO_RECENT = 6;
//	private static final int INDEX_AUDIO_TITLE = 7;
//	private static final int INDEX_IMAGE = 8;
//	private static final int INDEX_IMAGE_ALL = 9;
//	private static final int INDEX_IMAGE_CAMERA = 10;
//	private static final int INDEX_IMAGE_RECENT = 11;
//	private static final int INDEX_IMAGE_TITLE = 12;
//	private static final int INDEX_VIDEO = 13;
//	private static final int INDEX_VIDEO_ALL = 14;
//	private static final int INDEX_VIDEO_CAMERA = 15;
//	private static final int INDEX_VIDEO_RECENT = 16;
//	private static final int INDEX_VIDEO_TITLE = 17;
	
//	private static final String[] indice = { 
//		"/", 
//		"/audio", 
//		"/audio/album", "/audio/artist", "/audio/playlist", "/audio/song", "/audio/recent", "/audio/title",
//		"/image", 
//		"/image/all", "/image/camera", "/image/recent", "/image/title",
//		"/video", 
//		"/video/all", "/video/camera", "/video/recent", "/video/title", };
//
//	private static final String[][] lists = {
//	/* / */{ "audio", "image", "video" },
//	/* audio */{ "album", "artist", "playlist", "song", "recent", "title" }, 
//	null, null, null, null, null, null,
//	/* image */{ "all", "camera", "recent", "title" }, 
//	null, null, null, null,
//	/* video */{ "all", "camera", "recent", "title" }, 
//	null, null, null, null,};

	private static final int INDEX_ = 0;
	private static final int INDEX_AUDIO = 1;
	private static final int INDEX_AUDIO_RECENT = 2;
	private static final int INDEX_AUDIO_TITLE = 3;
	private static final int INDEX_IMAGE = 4;
	private static final int INDEX_IMAGE_RECENT = 5;
	private static final int INDEX_IMAGE_TITLE = 6;
	private static final int INDEX_VIDEO = 7;
	private static final int INDEX_VIDEO_RECENT = 8;
	private static final int INDEX_VIDEO_TITLE = 9;
	
	private static final String[] indice = { 
		"/", 
		"/audio", 
		"/audio/recent", "/audio/title",
		"/image", 
		"/image/recent", "/image/title",
		"/video", 
		"/video/recent", "/video/title", };

	private static final String[][] lists = {
	/* / */{ "audio", "image", "video" },
	/* audio */{ "recent", "title" }, 
	null, null,
	/* image */{ "recent", "title" }, 
	null, null,
	/* video */{ "recent", "title" }, 
	null, null,};
	private static final String LOG_TAG = "MediaFileImpl";
	
	private static final int MAX_COUNT = 32;

	private static ArrayList<MediaInfo> videolist = new ArrayList<MediaInfo>();
	
	private static boolean videoloaded;
	
	private static ArrayList<MediaInfo> recentVideolist = new ArrayList<MediaInfo>();
	private static boolean recentVideoloaded;
	private static final boolean needsIcon = false;

	synchronized private static void loadAudioList() {
		if (audioloaded) {
			return;
		}
		//
		final String by = MediaStore.Audio.Media.TITLE;
		Context ctx = (Context) fs.getContext();
		MediaUtils.loadAudio(ctx, audiolist, by, Integer.MAX_VALUE, needsIcon);
		//
		audioloaded = true;
	}
	
	synchronized private static void loadRecentAudioList() {
		if (recentAudioloaded) {
			return;
		}
		//
		final String by = MediaUtils.AUDIO_SORT_BY_DATE_DESC;
		Context ctx = (Context) fs.getContext();
		MediaUtils.loadAudio(ctx, recentAudiolist, by, MAX_COUNT, needsIcon );
		//
		recentAudioloaded = true;
	}

	synchronized private static void loadImageList() {
		if (imageloaded) {
			return;
		}

		final String by = MediaStore.Images.Media.TITLE;
		Context ctx = (Context) fs.getContext();
		MediaUtils.loadImage(ctx, imagelist, by, Integer.MAX_VALUE);
		//
		imageloaded = true;
	}
	
	synchronized private static void loadRecentImageList() {
		if (recentImageloaded) {
			return;
		}
		
		final String by = MediaUtils.IMAGE_SORT_BY_DATE_DESC;
		Context ctx = (Context) fs.getContext();
		MediaUtils.loadImage(ctx, recentImagelist, by, MAX_COUNT);
		
		recentImageloaded = true;
	}

	synchronized private static void loadVideoList() {
		if (videoloaded) {
			return;
		}
		final String by = MediaStore.Video.Media.DISPLAY_NAME;
		Context ctx = (Context) fs.getContext();
		MediaUtils.loadVideo(ctx, videolist, by, Integer.MAX_VALUE);
		//
		videoloaded = true;
	}
	
	synchronized private static void loadRecentVideoList() {
		if (recentVideoloaded) {
			return;
		}
		final String by = MediaUtils.VIDEO_SORT_BY_DATE_DESC;
		Context ctx = (Context) fs.getContext();
		MediaUtils.loadVideo(ctx, recentVideolist, by, MAX_COUNT);
		//
		recentVideoloaded = true;
	}
	
	private static int match(String path) {
		for (int i = 0; i < indice.length; i++) {
			if (indice[i].equals(path)) {
				return i;
			}
		}
		return -1;
	}

	private static String[] toArray(ArrayList<MediaInfo> list) {
		if (list == null) {
			return new String[0];
		}
		int sz = list.size();
		String[] sa = new String[sz];
		for (int i = 0; i < sz; i++) {
			ItemInfo ai = list.get(i);
			sa[i] = ai.id;
		}
		return sa;
	}

	private int index;

	private MediaInfo info;

	/**
	 * @param uri
	 */
	public MediaFileImpl(URI uri) {
		super(uri);
		if (DEBUG) {
			Log.d(LOG_TAG, "MediaFileImpl uri: " + uri);
		}
		//
		String p = path(uri);
		int i = match(p);
		this.index = i;
		this.info = null;
		if (i != -1) {
			return;
		}
		this.info = findItem(p);
	}

	protected MediaFileImpl(URI uri, MediaInfo info) {
		super(uri);
		//
		if (DEBUG) {
			Log.d(LOG_TAG, "MediaFileImpl uri: " + uri +" info: " + info);
		}
		String p = path(uri);
		this.index = match(p);
		this.info = info;
	}

	@Override
	public boolean canExecute() {
		return isFile();
	}

	@Override
	public boolean canRead() {
		return true;
	}

	@Override
	public boolean canWrite() {
		return false;
	}

	@Override
	public boolean create() {
		return false;
	}

	@Override
	public boolean delete() {
		return false;
	}

	@Override
	public boolean execute() {
		Intent i = null;
//		int idx = index;
//		switch (idx) {
//		case INDEX_AUDIO_ALBUM: {
//			i = new Intent(Intent.ACTION_PICK);
//			i.setDataAndType(Uri.EMPTY, "vnd.android.cursor.dir/album");
//			break;
//		}
//		case INDEX_AUDIO_ARTIST: {
//			i = new Intent(Intent.ACTION_PICK);
//			i.setDataAndType(Uri.EMPTY, "vnd.android.cursor.dir/artistalbum");
//			break;
//		}
//		case INDEX_AUDIO_PLAYLIST: {
//			i = new Intent(Intent.ACTION_PICK);
//			i.setDataAndType(Uri.EMPTY,MediaStore.Audio.Playlists.CONTENT_TYPE);
//			break;
//		}
//		case INDEX_AUDIO_SONG: {
//			i = new Intent(Intent.ACTION_PICK);
//			i.setDataAndType(Uri.EMPTY, "vnd.android.cursor.dir/track");
//			break;
//		}
//		case INDEX_IMAGE_ALL: {
//			i = new Intent(Intent.ACTION_VIEW);
//			i.setDataAndType(Uri.EMPTY, Images.Media.CONTENT_TYPE);
//			i.putExtra("windowTitle", "All pictures");

//			Uri uri = Images.Media.INTERNAL_CONTENT_URI;
//			i = new Intent(Intent.ACTION_VIEW, uri);
//			i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
//			i.putExtra("windowTitle", "All pictures");
//			i.putExtra("mediaTypes", Buckets.INCLUDE_IMAGES);
			
//			break;
//		}
//		case INDEX_IMAGE_CAMERA: {
//			Uri uri = Images.Media.INTERNAL_CONTENT_URI.buildUpon()
//					.appendQueryParameter("bucketId",
//							Buckets.CAMERA_IMAGE_BUCKET_ID).build();
//			i = new Intent(Intent.ACTION_VIEW, uri);
//			i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
//			i.putExtra("windowTitle", "Camera pictures");
//			i.putExtra("mediaTypes", Buckets.INCLUDE_IMAGES);
//			break;
//		}
//		case INDEX_VIDEO_ALL: {
//			i = new Intent(Intent.ACTION_VIEW);
//			i.setDataAndType(Uri.EMPTY, Video.Media.CONTENT_TYPE);
//			i.putExtra("windowTitle", "All videos");
		
//			Uri uri = Video.Media.INTERNAL_CONTENT_URI;
//			i = new Intent(Intent.ACTION_VIEW, uri);
//			i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
//			i.putExtra("windowTitle", "All videos");
//			i.putExtra("mediaTypes", Buckets.INCLUDE_VIDEOS);

//			break;
//		}
//		case INDEX_VIDEO_CAMERA:{
//			Uri uri = Video.Media.INTERNAL_CONTENT_URI.buildUpon()
//			.appendQueryParameter("bucketId",
//					Buckets.CAMERA_IMAGE_BUCKET_ID).build();
//			i = new Intent(Intent.ACTION_VIEW, uri);
//			i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
//			i.putExtra("windowTitle", "Camera videos");
//			i.putExtra("mediaTypes", Buckets.INCLUDE_VIDEOS);
//			break;
//		}
//		default:
//		}
		try {
			MediaInfo mi = info;
			if (i == null && mi != null && mi.file != null) {
				Uri uri = Uri.parse(mi.file.toURI().toString());
				i = new Intent(Intent.ACTION_VIEW);
				i.setDataAndType(uri, mi.mimeType);
				if (DEBUG) {
					Log.d(LOG_TAG,  "uri: " + uri);
				}
			}
			if (DEBUG) {
				Log.d(LOG_TAG, "execute " + i);
			}
			if (i == null) {
				return false;
			}
			//
			Context ctx = (Context) fs.getContext();
			i.setFlags(i.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
			ctx.startActivity(i);
			return true;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return false;
	}

	@Override
	public boolean exists() {
		return true;
	}

	private MediaInfo findItem(ArrayList<MediaInfo> list, String p) {
		if (DEBUG) {
			Log.d(LOG_TAG, "findItem found: " + p);
		}
		if (list != null) {
			String n = name(p);
			for (MediaInfo i : list) {
				if (i.id.equals(n)) {
					if (DEBUG) {
						Log.d(LOG_TAG, "findItem found: " + i);
					}
					return i;
				}
			}
		}
		return null;
	}

	private MediaInfo findItem(String p) {
		int i = matchWith(p);
		switch (i) {
		case INDEX_AUDIO_TITLE:
			loadAudioList();
			return findItem(audiolist, p);
		case INDEX_IMAGE_TITLE:
			loadImageList();
			return findItem(imagelist, p);
		case INDEX_VIDEO_TITLE:
			loadVideoList();
			return findItem(videolist, p);
		case INDEX_AUDIO_RECENT:
			loadRecentAudioList();
			return findItem(recentAudiolist, p);
		case INDEX_IMAGE_RECENT:
			loadRecentImageList();
			return findItem(recentImagelist, p);
		case INDEX_VIDEO_RECENT:
			loadRecentVideoList();
			return findItem(recentVideolist, p);
		}
		return null;
	}

	@Override
	public String getContentType() {
		MediaInfo mi = info;
		if (mi != null && mi.mimeType != null) {
			return mi.mimeType;
		}
		return super.getContentType();
	}

	@Override
	public String getDisplayName() {
		MediaInfo i = info;
		if (i != null) {
			return i.title;
		}
		return super.getName();
	}

	@Override
	public Object getIcon() {
//		int i = index;
//		switch(i) {
//		case INDEX_AUDIO_ALBUM:
//			return Icons.ICON_ALBUM;
//		case INDEX_AUDIO_ARTIST:
//			return Icons.ICON_ARTIST;
//		case INDEX_AUDIO_PLAYLIST:
//			return Icons.ICON_PLAYLIST;
//		case INDEX_AUDIO_SONG:
//			return Icons.ICON_SONG;
//		case INDEX_IMAGE_ALL:
//			return Icons.ICON_GALLERY;
//		case INDEX_IMAGE_CAMERA:
//			return Icons.ICON_GALLERY;
//		case INDEX_VIDEO_ALL:
//			return Icons.ICON_GALLERY;
//		case INDEX_VIDEO_CAMERA:
//			return Icons.ICON_GALLERY;
//		default:
//		}
		MediaInfo mi = info;
		if (mi != null && mi.icon != null) {
			return mi.icon;
		}
		return super.getIcon();
	}

	@Override
	public InputStream getInputStream() {
		MediaInfo i = info;
		if (i != null && i.file != null) {
			try {
				return new java.io.FileInputStream(i.file);
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			}
		}
		return null;
	}

	@Override
	public long getLastModified() {
		MediaInfo i = info;
		if (i != null) {
			return i.date;
		}
		return 0;
	}

	@Override
	public long getLength() {
		MediaInfo i = info;
		if (i != null) {
			return i.size;
		}
		return 0;
	}

	@Override
	public String getName() {
		MediaInfo i = info;
		if (i != null) {
			return i.id;
		}
		return super.getName();
	}

	@Override
	public OutputStream getOutputStream() {
		return null;
	}

	@Override
	public String getSortKey() {
		MediaInfo i = info;
		if (i != null) {
			return i.sortkey;
		}
		return super.getSortKey();
	}

	@Override
	public boolean isDirectory() {
		return !isFile();
	}

	@Override
	public boolean isFile() {
		int i = index;
		switch(i) {
		case INDEX_:
		case INDEX_AUDIO:
		case INDEX_IMAGE:
		case INDEX_VIDEO:
			return false;
//		case INDEX_AUDIO_ALBUM:
//		case INDEX_AUDIO_ARTIST:
//		case INDEX_AUDIO_PLAYLIST:
//		case INDEX_AUDIO_SONG:
//		case INDEX_IMAGE_ALL:
//		case INDEX_IMAGE_CAMERA:
//		case INDEX_VIDEO_ALL:
//		case INDEX_VIDEO_CAMERA:
//			return true;
		default:
		}
		MediaInfo mi = info;
		if (mi != null && mi.file != null) {
			return true;
		}
		return false;
	}

	@Override
	public boolean isLocal() {
		return true;
	}

	@Override
	public boolean isNative() {
		MediaInfo i = info;
		if (i != null && i.file != null) {
			return true;
		}
		return false;
	}
	
	@Override
	public String[] list() {
		int i = index;
		if (i != -1) {
			String[] l = lists[i];
			if (l != null) {
				return l;
			}
			//
			switch(i) {
			case INDEX_AUDIO_TITLE:
				loadAudioList();
				return toArray(audiolist);
			case INDEX_IMAGE_TITLE:
				loadImageList();
				return toArray(imagelist);
			case INDEX_VIDEO_TITLE:
				loadVideoList();
				return toArray(videolist);
			case INDEX_AUDIO_RECENT:
				loadRecentAudioList();
				return toArray(recentAudiolist);
			case INDEX_IMAGE_RECENT:
				loadRecentImageList();
				return toArray(recentImagelist);
			case INDEX_VIDEO_RECENT:
				loadRecentVideoList();
				return toArray(recentVideolist);
			default:
				break;
			}
		}
		return null;
	}

	@Override
	public IFile[] listFiles() {
		int i = index;
		if (i != -1 && lists[i] != null) {
			return super.listFiles();
		}
		ArrayList<MediaInfo> al = null;
		switch(i) {
		case INDEX_AUDIO_TITLE:
			loadAudioList();
			al = (audiolist);
			break;
		case INDEX_IMAGE_TITLE:
			loadImageList();
			al = (imagelist);
			break;
		case INDEX_VIDEO_TITLE:
			loadVideoList();
			al = (videolist);
			break;
		case INDEX_AUDIO_RECENT:
			loadRecentAudioList();
			al = (recentAudiolist);
			break;
		case INDEX_IMAGE_RECENT:
			loadRecentImageList();
			al = (recentImagelist);
			break;
		case INDEX_VIDEO_RECENT:
			loadRecentVideoList();
			al = (recentVideolist);
			break;
		default:
			break;
		}
		if (al == null) {
			return new IFile[0];
		}
		return listFiles(al);
	}

	private IFile[] listFiles(ArrayList<MediaInfo> al) {
		int len = al.size();
		IFile[] rl = new IFile[len];
		for (int i = 0; i < len; i++) {
			MediaInfo ai = al.get(i);
			URI pu = uri.resolve(uri.getPath() + "/" + ai.id);
			rl[i] = newInstance(pu, ai);
		}
		return rl;
	}

	private int matchWith(String p) {
		if (p.startsWith(indice[INDEX_AUDIO_TITLE])) {
			return INDEX_AUDIO_TITLE;
		}
		if (p.startsWith(indice[INDEX_IMAGE_TITLE])) {
			return INDEX_IMAGE_TITLE;
		}
		if (p.startsWith(indice[INDEX_VIDEO_TITLE])) {
			return INDEX_VIDEO_TITLE;
		}
		if (p.startsWith(indice[INDEX_AUDIO_RECENT])) {
			return INDEX_AUDIO_RECENT;
		}
		if (p.startsWith(indice[INDEX_IMAGE_RECENT])) {
			return INDEX_IMAGE_RECENT;
		}
		if (p.startsWith(indice[INDEX_VIDEO_RECENT])) {
			return INDEX_VIDEO_RECENT;
		}
		return -1;
	}

	@Override
	public boolean mkdir() {
		return false;
	}

	@Override
	public boolean move(URI uri) {
		return false;
	}

	private IFile newInstance(URI pu, MediaInfo ai) {
		return new MediaFileImpl(pu, ai);
	}

	@Override
	public void refresh() {
		audioloaded = false;
		imageloaded = false;
		videoloaded = false;
		//
		audiolist.clear();
		imagelist.clear();
		videolist.clear();
		//
		recentAudioloaded = false;
		recentImageloaded = false;
		recentVideoloaded = false;
		//
		recentAudiolist.clear();
		recentImagelist.clear();
		recentVideolist.clear();
	}

	@Override
	public URI toRealURI() {
		MediaInfo mi = info;
		if (mi != null && mi.file != null) {
			return mi.file.toURI();
		}
		return super.toRealURI();
	}
}
